/**
 * #info
 *
 *@author   wuwg
 *@createTime   2018/03/20
 *@updateTime   2018/04/08
 *@description  form  component  form 组件
 */
/**
 * #item
 *
 * @type        aty-form
 * @cn          表单
 * @menu        表单
 * @order   10
 * @stPlugin    true
 * @stContainer true
 */

import config from '../../../config/config.js'

// mixins
import Emitter from '../../../mixins/emitter.js'

const componentName = config.prefix + '-form'

// module
const module = {
  name: componentName,
  mixins: [Emitter],
  components: { },
  props: {
    /**
     * #property
     *
     * @name    labelWidth
     * @cn      标签宽度
     * @group   标签
     * @type    number
     * @bind    must
     * @value  80
     * @description  表单区域下所有标签的宽度，所有的 Form-item 都会继承 Form 组件的 label-width 的值
     */
    labelWidth: {
      type: Number,
      default: 80
    },
    /**
     * #property
     *
     * @name    labelPosition
     * @cn      标签位置
     * @group   标签
     * @type    list
     * @options [left,right,top]
     * @value    right
     * @description  表单域标签的位置，取值为 [left、right、top]中的其中一个,默认right
     */
    labelPosition: {
      validator (value) {
        return Artery.isOneOf(value, ['left', 'right', 'top'])
      },
      default: 'right'
    },
    /**
     * #property
     *
     * @name    inline
     * @cn      是否内联
     * @group   基本属性
     * @type    boolean
     * @value  false
     * @description  表单区域下所有的 Form-item是否是内联元素
     */
    inline: {
      type: Boolean,
      default: false
    },
    /**
     * #property
     *
     * @name    autocomplete
     * @cn      是否自动完成
     * @group   控制
     * @type    list
     * @options [on,off]
     * @value    off
     * @description  表单区域下所有的表单元素，autocomplete属性，取值为 [on, off]中的其中一个,默认off
     */
    autocomplete: {
      validator (value) {
        return Artery.isOneOf(value, ['on', 'off'])
      },
      default: 'off'
    },
    /**
     * #property
     *
     * @name    url
     * @cn      提交地址
     * @group   基本属性
     * @type    string
     * @description  表单区域submit 提交的url。
     */
    url: {
      type: String
    },
    /**
     * #property
     *
     * @name    data
     * @cn      提交和初始化的数据对象
     * @group   数据
     * @type    object,array
     * @bind    must
     * @description  提交和初始化的数据对象。
     */
    data: {
      type: [Object, Array]
    }
  },
  data () {
    return {
      fields: [],
      multipartSubmit: false
    }
  },
  watch: {
    data (newVal) {
      this.broadcast(config.prefix + '-upload', 'update-data', newVal || {})
    }
  },
  computed: {
    classes () {
      return [
        `${componentName}`,
        {
          [`${componentName}-inline`]: this.inline
        }
      ]
    }
  },
  methods: {
    /**
     * #method
     *
     * @name   resetFields
     * @param  callback {function} 回调函数
     * @description    对整个表单进行重置
     */
    resetFields (callback) {
      this.fields.forEach(field => {
        if (Artery.type(field.reset) === 'function') {
          field.reset()
        }
      })

      // 执行回调函数
      if (Artery.type(callback) == 'function') {
        callback()
      }
    },
    /**
     * #method
     *
     * @name   validate
     * @returns {Promise}
     * @description    对整个表单进行校验，参数为检验完的回调，会返回一个 Boolean 表示成功与失败
     */
    validate: function () {
      return new Promise((resolve, reject) => {
        let count = 0
        let error
        /*
         *  forEach 循环所有
         *   validate是采取的异步方式验证，
         */
        this.fields.forEach(field => {
          field.validate(errors => {
            // 只要有一个失败，那么就验证失败
            if (errors) {
              error = errors
            }
            // 返回了结果，执行回调函数。
            if (++count === this.fields.length) {
              if (error) {
                reject(error)
              } else {
                resolve()
              }
            }
          })
        })
      })
    },
    /**
     * #method
     *
     * @name   clearValidateInfo
     * @description    清空表单校验信息
     */
    clearValidateInfo: function () {
      this.fields.forEach(field => {
        field.clearValidateInfo()
      })
    },
    /**
     * #method
     *
     * @name   getData
     * @param   noValidate ｛boolean｝ 不需要验证，默认需要验证
     * @param   callback ｛function｝  回调函数，参数为data
     * @description  获取表单中的数据对象，默认需要验证成功后才会获取数据，如果 noValidate=true. 那么直接返回数据，不需要进行验证。
     */
    getData: function (noValidate, callback) {
      const _this = this
      let _noValidate = noValidate
      let _callback = callback
      // 如果 _noValidate ==function，那么就需要验证
      if (Artery.type(_noValidate) == 'function') {
        _noValidate = false
        _callback = noValidate
      }
      if (Artery.type(_callback) != 'function') {
        alert('callback是必须参数！')
        return
      }
      // 如果不验证
      if (_noValidate) {
        _callback(_this.data)
      } else {
        // 否则需要先验证，再获取数据
        this.validate().then(() => {
          _callback(_this.data)
        }).catch(error => {
          console.error(error)
          _callback(null)
        })
      }
    },
    /**
     * #method
     *
     * @name    submit
     * @param   url ｛String｝ 请求url,如不传默认取form的url属性
     * @returns {Promise}
     * @description  首先进行数据验证，验证通过后发送post请求提交表单数据,默认ContentType:Application/json
     */
    submit: function (url) {
      return new Promise((resolve, reject) => {
        const postUrl = url || this.url
        if (postUrl) {
          this.getData(data => {
            if (data) {
              if (this.multipartSubmit) {
                const config = {
                  headers: {
                    'Content-Type': 'multipart/form-data'
                  },
                  timeout: 0, // 上传默认不超时
                  onUploadProgress: (e) => { // 对原生进度事件的处理
                    if (e.total > 0) {
                      e.percent = e.loaded / e.total * 100
                      /**
                       * #event
                       *
                       * @name    upload-progress
                       * @param   e  原生ajax上传进度事件, artery-ui给添加了percent属性
                       * @body    console.log(e.percent)
                       * @description  原生上传进度事件
                       */
                      this.$emit('upload-progress', e)
                    }
                  }
                }
                const formData = new FormData()
                for (const key in data) {
                  if (Object.prototype.toString.call(data[key]) === '[object File]') {
                    formData.append(key.split('_')[0], data[key])
                  } else {
                    formData.append(key, data[key])
                  }
                }
                Artery.ajax.post(postUrl, formData, config).then(result => {
                  resolve(result)
                  // 清空上传控件缓存的列表文件
                  this.broadcast(config.prefix + '-upload', 'update-data', {})
                }).catch(error => {
                  reject(error)
                })
              } else {
                Artery.ajax.post(postUrl, data).then(result => {
                  // http请求成功了,不需要管业务是否成功,直接把服务返回的对象给他
                  resolve(result)
                }).catch(error => {
                  reject(error)
                })
              }
            } else {
              reject({
                message: '参数格式未通过验证！',
                code: 400
              })
            }
          })
        } else {
          reject('缺少url参数,请传递参数或在aty-form上指定url属性')
        }
      })
    }
  },
  updated () { },
  created () {
    // 事件监听
    this.$on('form-item-add', (field) => {
      if (field) {
        this.fields.push(field)
      }
      return false
    })
    // 事件监听
    this.$on('form-item-remove', (field) => {
      if (field) {
        this.fields.splice(this.fields.indexOf(field), 1)
      }
      return false
    })
  },
  mounted () {}
}
export default module
